VSCode Extension 模块
30 秒理解:这个模块为什么存在
VSCode Extension 模块是 Loki Mode 在 IDE 侧的“控制塔台”。它解决的不是算法问题,而是工程协同问题:如何把命令行(CLI)、后端 API、实时事件流和 VS Code 交互体验粘成一个稳定系统。
如果没有它,开发者需要手动:启动 CLI 服务、轮询接口、解析日志、对齐状态;而且这些步骤在不同机器和工作区会因为配置差异不断出错。这个模块的价值就是把这些重复且脆弱的操作收敛为:
- 可管理的进程生命周期(
CliExecutor/CliExecutorEvents) - 可编译校验的协议契约(
api/types.ts) - 可监听、可更新的工作区配置入口(
Config)
阅读地图(先看这里)
为了让新同事快速进入“作者心智模型”,建议按以下顺序阅读子文档:
-
api_contracts_and_events.md
聚焦vscode-extension/src/api/types.ts:为什么把 API/SSE 事件设计成联合类型、哪些字段是跨模块隐式契约、哪些接口仍处于 planned/deprecated 状态。 -
cli_process_lifecycle_events.md
聚焦vscode-extension/src/cli/executor.ts:CLI 路径探测、服务启动/停止状态机、server:*事件如何驱动 UI 与控制逻辑。 -
configuration_and_settings_access.md
聚焦vscode-extension/src/utils/config.ts:loki配置命名空间、默认值策略、变更监听与键级变更检测。
主文档重点回答“架构角色与设计动机”;字段级与函数级细节请看以上子文档。
架构设计
配置管理] API[API Types
类型定义] CLI[CliExecutor
CLI执行器] ACM[API Client Manager
API客户端] end subgraph "External Resources" LCLI[Loki CLI] LSERV[Loki Server Process] end subgraph "Loki Mode Backend" DASH[Dashboard Server] API_S[API Server] EB[Event Bus] end VSC --> CFG VSC --> CLI VSC --> ACM CFG --> ACM CLI --> LCLI CLI --> LSERV ACM --> LSERV LSERV --> DASH LSERV --> API_S API_S --> EB DASH --> EB style CFG fill:#e1f5fe style API fill:#e1f5fe style CLI fill:#e1f5fe style ACM fill:#e1f5fe
组件职责划分
核心组件详解
1. Config(配置管理)
Config 类是 VSCode Extension 的配置中心,提供对 VSCode 设置系统的类型安全访问。它封装了 vscode.workspace.getConfiguration API,为 Loki Mode 相关的所有配置项提供结构化访问。
核心职责:
- 提供默认配置值(API 端口、主机地址、轮询间隔等)
- 支持工作区和全局级别的配置作用域
- 监听配置变更事件,实现动态响应
- 提供便捷的配置更新方法
关键设计决策:
- 使用 TypeScript 的
keyof约束确保配置键的类型安全 - 静态方法设计便于全局访问,无需实例化
- 配置节(Section)统一使用
'loki'前缀,避免命名冲突
使用示例:
// 读取配置
const provider = Config.provider; // 'claude' | 'codex' | 'gemini'
const apiUrl = Config.apiBaseUrl; // http://localhost:8080
// 更新配置
await Config.update('provider', 'gemini', vscode.ConfigurationTarget.Workspace);
// 监听变更
Config.onDidChange((e) => {
if (Config.didChange(e, 'apiPort')) {
// 重新初始化 API 客户端
}
});
2. API Types(类型定义)
types.ts 文件定义了整个扩展与 Loki Mode 后端交互所需的全部 TypeScript 接口。这些类型不仅服务于 VSCode Extension 内部使用,更重要的是确保与 Dashboard Backend 的 API 契约保持一致。
类型系统架构:
执行阶段] TaskStatus[TaskStatus
任务状态] SessionState[SessionState
会话状态] Provider[Provider
AI提供商] Task[Task
任务实体] SessionStatus[SessionStatus
会话状态] end subgraph "API 请求/响应类型" ApiResponse[ApiResponse
基础响应] HealthResponse[HealthResponse
健康检查] StartRequest[StartRequest
启动请求] StartResponse[StartResponse
启动响应] end subgraph "SSE 事件类型" BaseEvent[BaseEvent
事件基类] SessionEvents[会话事件
started/stopped/paused/resumed] PhaseEvents[阶段事件
started/completed] TaskEvents[任务事件
started/progress/completed/failed] LogEvent[LogEvent
日志事件] ErrorEvent[ErrorEvent
错误事件] end BaseEvent --> SessionEvents BaseEvent --> PhaseEvents BaseEvent --> TaskEvents BaseEvent --> LogEvent BaseEvent --> ErrorEvent
关键类型说明:
Phase(执行阶段)
定义了 Loki Mode 工作流的标准阶段:idle → initializing → planning → implementing → testing → reviewing → deploying → completed/failed。每个会话在任一时刻只能处于一个阶段,阶段转换会触发 phase:started 和 phase:completed 事件。
SessionStatus(会话状态) 这是与 Dashboard Server 最关键的共享类型。它包含了服务器返回的完整状态信息:进程 ID、状态文本、当前阶段、当前任务、待处理任务数、使用的 AI 提供商等。扩展通过轮询或 SSE 持续接收此类型的数据来更新 UI。
LokiEvent(事件联合类型)
使用 TypeScript 的联合类型和 discriminated union 模式,确保事件处理的类型安全。每个事件都有明确的 type 字段作为判别式,配合 EventCallbacks 接口实现类型安全的事件订阅。
版本兼容性注意事项:
- 注释中明确标注了与 Dashboard Server 端点的对应关系(如
matches dashboard/server.py /health endpoint) - 某些端点标注为
PLANNED或deprecated,提示实现状态
3. CliExecutor(CLI 执行器)
CliExecutor 是 VSCode Extension 中最复杂的组件,负责管理 Loki CLI 进程的完整生命周期。它继承自 Node.js 的 EventEmitter,采用事件驱动架构通知调用方状态变更。
状态机设计:
核心能力:
1. CLI 自动检测
ensureCliPath() 方法实现了智能的 CLI 路径解析:
- 优先使用用户显式配置的路径
- 缓存检测结果避免重复文件系统操作
- 提供清晰的安装指导(npm、Homebrew 等)
2. 服务器生命周期管理
- 启动流程:检查现有进程 → 生成子进程 → 监听输出流 → 等待健康检查 → 状态通知
- 停止流程:发送 SIGTERM → 等待优雅退出 → 超时后 SIGKILL
- 状态缓冲:收集 stdout/stderr 用于故障诊断
3. 双重执行模式
executeCommand():Promise-based,适合短时间命令executeCommandStreaming():流式输出,适合长时间运行的任务
事件系统:
export interface CliExecutorEvents {
'server:starting': () => void; // 开始启动
'server:started': (port: number) => void; // 启动成功
'server:stopping': () => void; // 开始停止
'server:stopped': (code: number | null) => void; // 已停止
'server:error': (error: Error) => void; // 错误发生
'server:output': (data: string) => void; // stdout 输出
'server:stderr': (data: string) => void; // stderr 输出
}
错误处理策略:
- 启动超时:可配置(默认 30 秒),超时后自动终止进程
- 进程崩溃:
exit事件处理,区分正常退出和异常终止 - 端口冲突:启动前主动检测,避免重复启动
资源管理:
dispose() 方法确保扩展停用时的资源清理,这是 VSCode Extension API 的最佳实践要求。
数据流与交互模式
会话启动流程
实时事件处理流程
配置参考
可用配置项
| 配置键 | 类型 | 默认值 | 描述 |
|---|---|---|---|
loki.provider |
string |
'claude' |
AI 提供商选择,可选值:claude、codex、gemini |
loki.apiPort |
number |
8080 |
Loki API 服务器端口 |
loki.apiHost |
string |
'localhost' |
Loki API 服务器主机 |
loki.autoConnect |
boolean |
true |
扩展激活时自动连接服务器 |
loki.showStatusBar |
boolean |
true |
在状态栏显示 Loki 状态 |
loki.logLevel |
string |
'info' |
日志级别:debug、info、warn、error |
loki.pollingInterval |
number |
5000 |
状态轮询间隔(毫秒) |
loki.prdPath |
string |
'' |
默认 PRD 文件路径 |
配置示例(settings.json)
{
"loki.provider": "claude",
"loki.apiPort": 8080,
"loki.autoConnect": true,
"loki.showStatusBar": true,
"loki.logLevel": "debug",
"loki.pollingInterval": 3000,
"loki.prdPath": "${workspaceFolder}/docs/prd.md"
}
API 客户端使用模式
虽然提供的代码片段中未包含完整的 API 客户端实现,但基于 types.ts 中的定义,可以推断出标准的使用模式:
// 伪代码示例,展示预期使用方式
class LokiApiClient {
private baseUrl: string;
private eventSource?: EventSource;
private callbacks: Partial<EventCallbacks> = {};
constructor(config: ApiClientConfig) {
this.baseUrl = config.baseUrl;
}
// 启动会话
async startSession(prd: string, provider?: Provider): Promise<StartResponse> {
const request: StartRequest = { prd, provider };
const response = await fetch(`${this.baseUrl}/api/control/start`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(request)
});
return response.json();
}
// 获取状态
async getStatus(): Promise<SessionStatus> {
const response = await fetch(`${this.baseUrl}/api/status`);
return response.json();
}
// 订阅 SSE 事件
connectEventStream(): void {
this.eventSource = new EventSource(`${this.baseUrl}/api/events`);
this.eventSource.onmessage = (event) => {
const data: LokiEvent = JSON.parse(event.data);
this.handleEvent(data);
};
}
// 类型安全的事件处理
private handleEvent(event: LokiEvent): void {
switch (event.type) {
case 'task:progress':
this.callbacks['task:progress']?.(event);
break;
case 'log':
this.callbacks['log']?.(event);
break;
// ... 其他事件类型
}
}
// 类型安全的事件订阅
on<K extends keyof EventCallbacks>(
event: K,
callback: EventCallbacks[K]
): void {
this.callbacks[event] = callback;
}
}
错误处理与边界情况
常见错误场景
1. CLI 未安装
Error: Loki CLI not found. Please install it via npm (npm install -g loki-mode),
Homebrew (brew install loki-mode), or specify the path in settings.
处理建议:检查 CLI 安装状态,或在 VSCode 设置中指定 loki.cliPath。
2. 服务器启动超时 可能原因:
- 端口被占用(Config 中配置的端口已被其他进程使用)
- CLI 版本不兼容
- 系统资源不足
3. SSE 连接中断 网络波动或服务器重启会导致 SSE 连接断开。健壮的实现应包含:
- 自动重连机制(指数退避)
- 连接状态指示
- 降级到轮询模式
4. 类型不匹配 当 Dashboard Backend 更新而 VSCode Extension 未同步更新时,可能出现运行时类型错误。建议:
- 使用 zod 或 io-ts 进行运行时类型验证
- 在开发模式下启用严格类型检查
调试技巧
- 查看服务器输出:通过
CliExecutor.serverOutput和serverStderr获取原始输出 - 启用调试日志:设置
loki.logLevel为'debug' - 手动健康检查:在浏览器访问
http://localhost:8080/health - 验证 CLI 路径:在 VSCode 终端运行
which loki或loki --version
扩展开发指南
开发环境设置
# 克隆仓库
git clone <repository-url>
cd loki-mode/vscode-extension
# 安装依赖
npm install
# 编译
npm run compile
# 调试模式(在 VSCode 中按 F5)
# 这将打开一个新的 Extension Development Host 窗口
添加新的命令
- 在
package.json中声明命令:
{
"contributes": {
"commands": [
{
"command": "loki.myNewCommand",
"title": "Loki: My New Command"
}
]
}
}
- 在
src/extension.ts中注册处理函数:
export function activate(context: vscode.ExtensionContext) {
const disposable = vscode.commands.registerCommand('loki.myNewCommand', async () => {
// 实现命令逻辑
const config = Config.getAll();
// ...
});
context.subscriptions.push(disposable);
}
添加新的事件类型
- 在
types.ts中定义事件接口:
export interface MyCustomEvent extends BaseEvent {
type: 'custom:event';
data: {
field1: string;
field2: number;
};
}
- 更新联合类型:
export type LokiEvent =
| // ... 现有类型
| MyCustomEvent;
- 更新回调接口:
export interface EventCallbacks {
// ... 现有回调
'custom:event'?: (event: MyCustomEvent) => void;
}
与其他模块的关系
与 Dashboard Backend 的契约
VSCode Extension 与 Dashboard Backend 保持严格的 API 契约一致性。任何 Dashboard Backend 的 API 变更都需要同步更新 types.ts:
- 状态模型:
SessionStatus、Task等类型必须与 Dashboard Backend 的 Pydantic 模型保持字段一致 - 端点路径:注释中标注了每个类型对应的 Dashboard Server 端点
- 响应格式:区分直接返回和包装在
ApiResponse中的响应
与 SDK 的关系
VSCode Extension 内部实现了轻量级的 API 客户端,功能上类似于 TypeScript SDK 的子集。两者的区别:
| 特性 | VSCode Extension | TypeScript SDK |
|---|---|---|
| 目标环境 | VSCode Extension Host | 通用 Node.js/浏览器 |
| 依赖 | VSCode API | 无特殊依赖 |
| 功能范围 | 会话管理 + UI 集成 | 完整 API 覆盖 |
| 打包方式 | VSCode 插件包 | npm 包 |
在需要更复杂功能时,VSCode Extension 可以考虑依赖 TypeScript SDK 而非重复实现。
与 CLI 的集成
VSCode Extension 通过 CliExecutor 与 Loki CLI 紧密集成。这种设计允许:
- 从源代码构建的 CLI 开发版本进行测试
- 自动启动/停止服务器进程
- 捕获和分析 CLI 输出用于故障诊断
性能考虑
内存管理
CliExecutor的outputBuffer和stderrBuffer会持续增长,长时间运行的会话应考虑定期清理或限制缓冲区大小- EventSource 连接在不使用时应关闭,避免内存泄漏
网络优化
- 轮询间隔(
pollingInterval)默认为 5 秒,可根据网络条件调整 - SSE 连接相比轮询更高效,应优先使用
UI 响应性
- 长时间运行的 CLI 命令应使用
executeCommandStreaming避免阻塞 Extension Host - 大量日志事件到达时应考虑节流(throttling)或批量处理
已知限制与未来改进
当前限制
- 输入注入端点未实现:
InputResponse标注为PLANNED,目前无法通过 API 向运行中的会话发送输入 - 单会话限制:当前设计假设一次只能管理一个活跃会话
- 本地服务器假设:配置和实现都假设 Loki Server 在本地运行
建议改进方向
- 远程服务器支持:允许配置远程 Loki Server 地址
- 多会话管理:支持同时监控多个项目/会话
- 历史记录持久化:本地缓存会话历史,支持离线查看
- 增强的 diff 视图:集成 VSCode 的 diff 编辑器显示代码变更
- 任务内联操作:在编辑器内直接对 AI 生成的代码进行接受/拒绝操作
版本兼容性
| VSCode Extension 版本 | 兼容的 Loki CLI 版本 | 兼容的 Dashboard 版本 |
|---|---|---|
| 0.1.x | 0.1.x | 0.1.x |
建议保持 CLI、Dashboard 和 VSCode Extension 的版本同步,以确保 API 契约的一致性。